import logging
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve, QByteArray
from PySide6.QtGui import QColor, QBrush, QFont
from PySide6.QtWidgets import QListWidget, QAbstractItemView, QListWidgetItem
import re
from mutagen.id3 import ID3

class LyricsManager:
    def __init__(self, lyrics_list: QListWidget):
        self.lyrics_list = lyrics_list
        self.lyrics_data = {}
        self.current_lyric_index = 0
        self.current_file = None


    def parse_lrc(self, lyrics_content):
        print('正在解析歌词内容...')
        lyrics = []
        import re
        for line_num, line in enumerate(lyrics_content.split('\n'), 1):
            if line.startswith('['):
                try:
                    # 修改正则表达式匹配分钟:秒.毫秒格式
                    time_match = re.match(r'\[(\d{2}):(\d{2}\.\d{3})\]', line)
                    if not time_match:
                        logging.warning(f'第{line_num}行时间格式错误: {line.strip()}')
                        continue
                    minutes = int(time_match.group(1))
                    seconds_part = time_match.group(2).split('.')
                    seconds = int(seconds_part[0])
                    milliseconds = int(seconds_part[1].ljust(3, '0'))  # 补足三位毫秒
                    timestamp = int((minutes * 60 + seconds) * 1000 + milliseconds)  # 显式转换为整数类型
                    text = line.split(']', 1)[1].strip()
                    #lyrics.append((int(timestamp), text))  # 存储时间戳和文本元组
                    lyrics.append((timestamp, text))  # 存储时间戳和文本元组
                except Exception as e:
                    logging.warning(f'第{line_num}行解析失败: {str(e)} 内容: {line.strip()}')
        return sorted(lyrics, key=lambda x: x[0])

    def debug_scroll_lyrics(self, target_index):
        if not self.lyrics_list.count():
            return
        target_index = max(0, min(target_index, self.lyrics_list.count()-1))
        current_item = self.lyrics_list.item(target_index)
        self.lyrics_list.scrollToItem(current_item, QAbstractItemView.ScrollHint.PositionAtCenter)

    def update_lyrics(self, position):
        parsed_lyrics = self.lyrics_data.get(self.current_file, [])
        if not parsed_lyrics:
            self.lyrics_list.clear()
            return

        # 查找当前歌词索引
        current_time = position
        low, high = 0, len(parsed_lyrics) - 1
        while low <= high:
            mid = (low + high) // 2
            if current_time < parsed_lyrics[mid][0]:
                high = mid - 1
            else:
                low = mid + 1

        self.current_lyric_index = high if high >= 0 else low
        self.current_lyric_index = max(0, min(self.current_lyric_index, len(parsed_lyrics) - 1))

        # 清除所有项样式
        if self.lyrics_list.count() > 0:
            for i in range(self.lyrics_list.count()):
                item = self.lyrics_list.item(i)
                item.setBackground(QBrush(Qt.BrushStyle.NoBrush))
                item.setForeground(QBrush(Qt.BrushStyle.NoBrush))
                item.setTextAlignment(Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap)
                font = item.font()
                font.setBold(False)
                item.setFont(font)

        # 设置当前歌词高亮
        if 0 <= self.current_lyric_index < self.lyrics_list.count():
            current_item = self.lyrics_list.item(self.current_lyric_index)
            
            current_item.setSelected(True) #关联qss样式文件来设置高亮
            #current_item.setBackground(QColor(68, 74, 152))
            #current_item.setForeground(QBrush(QColor(255, 255, 255)))
            font = current_item.font()
            font.setBold(True)
            current_item.setFont(font)
        
        # 调用封装好的滚动方法
        self.debug_scroll_lyrics(self.current_lyric_index)

    # 先用_get_embedded_lyrics方法获取歌词，再用parse_lrc方法解析歌词，最后用load_lyrics加载歌词
    def load_lyrics(self, file_path):
        if file_path == self.current_file:
            return

        self.current_file = file_path
        try:
            if file_path not in self.lyrics_data:
                lyrics_content = self._get_embedded_lyrics(file_path)
                if not lyrics_content:
                    with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                        lyrics_content = f.read()
                self.lyrics_data[file_path] = self.parse_lrc(lyrics_content)

            self.lyrics_list.clear()
            for _, text in self.lyrics_data[file_path]:
                item = QListWidgetItem(text)
                item.setTextAlignment(Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap)
                self.lyrics_list.addItem(item)

            self.current_lyric_index = 0
        except Exception as e:
            logging.error(f'歌词加载失败: {str(e)}')
            self.lyrics_list.clear()

    def _get_embedded_lyrics(self, file_path):
        try:
            from pathlib import Path
            if file_path.lower().endswith('.mp3'):
                return self._get_embedded_mp3_lyrics(file_path)
            elif file_path.lower().endswith('.flac'):
                return self._get_embedded_flac_lyrics(file_path)
        except Exception as e:
            logging.warning(f'歌词解析失败: {str(e)}')
        return ''

    def _get_embedded_mp3_lyrics(self, file_path):
        from pathlib import Path
        from mutagen.id3 import ID3, USLT
        
        lrc_path = Path(file_path).with_suffix('.lrc')
        if lrc_path.exists():
            try:
                with open(lrc_path, 'rb') as f:
                    content = f.read()
                    for encoding in ['utf-8','utf-16','utf-16LE','gbk']:
                        try:
                            return content.decode(encoding)
                        except UnicodeDecodeError:
                            continue
            except Exception as e:
                print(f"读取外置歌词失败: {str(e)}")
        
        try:
            audio = ID3(file_path)
            for tag in audio.values():
                if isinstance(tag, USLT):
                    return tag.text
            return ''
        except Exception as e:
            print(f"Error reading lyrics from {file_path}: {e}")
            return ''

    def _get_embedded_flac_lyrics(self, file_path):
        from pathlib import Path
        from mutagen.flac import FLAC
        
        lrc_path = Path(file_path).with_suffix('.lrc')
        if lrc_path.exists():
            try:
                with open(lrc_path, 'rb') as f:
                    content = f.read()
                    for encoding in ['utf-8','utf-16','utf-16LE','gbk']:
                        try:
                            return content.decode(encoding)
                        except UnicodeDecodeError:
                            continue
            except Exception as e:
                logging.warning(f'外置歌词读取失败: {str(e)}')
        
        try:
            audio = FLAC(file_path)
            if 'lyrics' in audio:
                return '\n'.join(audio['lyrics'])
            return ''
        except Exception as e:
            logging.error(f'FLAC歌词解析失败: {str(e)}')
            return ''
